package com.kly.juc.atomic;

import lombok.Getter;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.*;

/**
 * @author admin
 * @date 2025/4/17
 */
public class AtomicDemo {

    public static void main(String[] args) {
        demo3();
    }

    public static void demo4() {
        LongAdder longAdder = new LongAdder();
        for (int i = 0; i < 1000; i++) {
            longAdder.increment();
        }

        LongAccumulator longAccumulator = new LongAccumulator(Long::sum, 0);
        for (int i = 0; i < 1000; i++) {
            longAccumulator.accumulate(2);
        }
    }

    /**
     * AtomicReferenceFieldUpdater
     */
    public static void demo3() {
        BankAccount2 bankAccount2 = new BankAccount2();
        int size = 10;
        CountDownLatch countDownLatch = new CountDownLatch(size);
        for (int j = 0; j < 10; j++) {

            CompletableFuture.runAsync(() -> {
                try {
                    for (int i = 0; i < 1000; i++) {
                        bankAccount2.addAmount3(bankAccount2);
                    }
                } catch (Exception e) {
                    throw new RuntimeException(e);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(bankAccount2.getMoney());
    }

    /**
     * AtomicInterFieldUpdater
     */
    public static void demo2() {
        BankAccount bankAccount = new BankAccount();
        int size = 10;
        CountDownLatch countDownLatch = new CountDownLatch(size);
        for (int j = 0; j < 10; j++) {

            CompletableFuture.runAsync(() -> {
                try {
                    for (int i = 0; i < 1000; i++) {
                        bankAccount.addAmount2(bankAccount);
                    }
                } catch (Exception e) {
                    throw new RuntimeException(e);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(bankAccount.getBalance());
    }

    /**
     * AtomicInteger
     */
    public static void demo1() {
        AtomicInteger atomicInteger = new AtomicInteger();
        int size = 10;
        CountDownLatch countDownLatch = new CountDownLatch(size);
        for (int i = 0; i < size; i++) {
            CompletableFuture.runAsync(() -> {
                try {
                    for (int j = 0; j < 500; j++) {

                    }
                } catch (Exception e) {
                    throw new RuntimeException(e);
                } finally {
                    countDownLatch.countDown();
                }
            });
        }

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(atomicInteger.get());
    }
}

@Getter
class BankAccount {
    public volatile int balance = 0;


    public void addAmount() {
        balance++;
    }

    static final AtomicIntegerFieldUpdater<BankAccount> updater = AtomicIntegerFieldUpdater.newUpdater(BankAccount.class, "balance");
    public void addAmount2(BankAccount bankAccount) {
        updater.getAndIncrement(bankAccount);
    }




}

@Getter
class BankAccount2 {
    public volatile double money = 0.0;

    static final AtomicReferenceFieldUpdater<BankAccount2, Double> updater2 = AtomicReferenceFieldUpdater.newUpdater(BankAccount2.class, Double.class, "money");
    public void addAmount3(BankAccount2 bankAccount) {
        updater2.getAndUpdate(bankAccount, money -> money + 1.5);
    }

}

